# @Time    : 2022/9/30 14:40
# @Author  : 南黎
# @FileName: 1.b MLPClassifier多层神经网络.py
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import preprocessing
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier

orgin_data=pd.read_csv("data1.csv").values
# a.数据归一化
# MaxAbsScaler根据最大值的绝对值进行标准化。假设某列原数据为x，则新数据为x/|max|
# 可以保证特征数据缩放到区间[-1,1]
max_abs_scaler = preprocessing.MaxAbsScaler()  # 注册一个预处理对象
sizeOfOne_data = max_abs_scaler.fit_transform(orgin_data)  # fit_transform(X[, y])	适合数据，然后转换它。

# 理论上按照一般流程来讲这里最好还是要划分训练集和测试集，但是数据样本总共就30，不划分其实也可以
X=sizeOfOne_data[:,0:2]#特征1和特征2
Y=sizeOfOne_data[:,2:].astype('int').ravel()#分类结果  #ravel()方法将数组维度拉成一维数组
#PS：如果不将数组维度拉成一维数组，会出现警告信息，但是不影响运行，这意味着规范书写
X_train, X_test, Y_train, Y_test = train_test_split(X, Y,test_size=0.2,random_state=0)
#train_test_split是交叉验证中常用的函数，功能是从样本中随机的按比例选取train data和testdata
# train_data：所要划分的样本特征集
# train_target：所要划分的样本结果
# test_size：样本占比，如果是整数的话就是样本的数量,0.2表示20%的测试集
# random_state：是随机数的种子。

# b.创建神经网络分类器

# mpl = MLPClassifier(hidden_layer_sizes=(5, 2), activation='logistic',solver='sgd')
mpl = MLPClassifier(hidden_layer_sizes=(5, 2), activation='logistic',solver='lbfgs')
# 1. hidden_layer_sizes :例如hidden_layer_sizes=(5, 2)，表示有两层隐藏层，第一层隐藏层有5个神经元，第二层也有2个神经元。
#
# 2. activation :激活函数,{‘identity’, ‘logistic’, ‘tanh’, ‘relu’}, 默认relu
#
# - identity：f(x) = x
#
# - logistic：其实就是sigmod,f(x) = 1 / (1 + exp(-x)).
#
# - tanh：f(x) = tanh(x).
#
# - relu：f(x) = max(0, x)
#
# 3. solver： {‘lbfgs’, ‘sgd’, ‘adam’}, 默认adam，用来优化权重
#
# - lbfgs：quasi-Newton方法的优化器
#
# - sgd：随机梯度下降
#
# - adam： Kingma, Diederik, and Jimmy Ba提出的机遇随机梯度的优化器
#
# 注意：默认solver ‘adam’在相对较大的数据集上效果比较好（几千个样本或者更多），对小数据集来说，lbfgs收敛更快效果也更好。
#
# 4. alpha :float,可选的，默认0.0001,正则化项参数
#
# 5. batch_size : int , 可选的，默认’auto’,随机优化的minibatches的大小batch_size=min(200,n_samples)，如果solver是’lbfgs’，分类器将不使用minibatch
#
# 6. learning_rate :学习率,用于权重更新,只有当solver为’sgd’时使用，{‘constant’，’invscaling’, ‘adaptive’},默认constant


# 训练神经网络模型
mpl.fit(X_train, Y_train.ravel())
# 打印模型预测评分
print('Score:\n', mpl.score(X_test, Y_test))

# c.可视化网络分类结果
# 划分网格区域
h = 0.02
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
Z = mpl.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
# 画三维等高线图，并对轮廓线进行填充
plt.contourf(xx, yy, Z, cmap='summer')
# 绘制散点图
class1_x = X[Y == 0, 0]#取得y值为0的第0索引位置（特征1）
class1_y = X[Y == 0, 1]#取得y值为0的第0索引位置（特征2）
l1 = plt.scatter(class1_x, class1_y, color='b', label="0")
class2_x = X[Y == 1, 0]#取得y值为1的第0索引位置（特征1）
class2_y = X[Y == 1, 1]#取得y值为1的第0索引位置（特征2）
l2 = plt.scatter(class2_x, class2_y, color='r', label="1")
plt.legend(handles=[l1, l2], loc='best')
plt.grid(True)
plt.savefig("1/1.c MLPClassifier多层神经网络可视化.png")
plt.show()